/*

    thermcap the thermal data collector program.
    thermcap collects CPU heating data and stores it in a csv and svg-graphic file
    Copyright (C) 2011  Giovanni Santostefano

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <string.h>

#include "thermal_cap.h"
#include "queue.h"

void signalhandler(int numsig);

/*Save a comma separated value file for store thermal data
the file can be loaded into a spreadsheet*/
int save_csv(char *csvname)
{
	FILE *datstream=NULL;
	FILE *csvstream=NULL;
	int c;
	
	if(!csvname)return -3;
	
	if(!(datstream=fopen("temp.dat","r"))) return -1;
	if(!(csvstream=fopen(csvname,"w"))) return -2;
	
	while((c=fgetc(datstream))!=EOF) {fputc(c,csvstream);}
	
	fclose(datstream);
	fclose(csvstream);
	
	printf("\n\nFile:%s saved!\n\n",csvname);
	
	return 0;
}


/*SVG creation function*/
/*TODO: this will completely rewritten*/
#define X_SCALE 5
int save_svg(char *svgname)
{
	int i=0;
	char therm_str[50];
	char *res=NULL;
	int num_samples=0; /*number of cpu thermal samples*/
	int cput=0; /*cpu thermal value*/
	
	FILE *datstream=NULL;
	FILE *svgstream=NULL;
	
	if(!svgname)return -3;
	
	if(!(datstream=fopen("temp.dat","r"))) return -1;
	if(!(svgstream=fopen(svgname,"w"))) return -2;
	
	/*collecting numeric data in a FIFO queue*/
	struct b_queue *queue=NULL;
	
	queue=b_queue_init();
	while((res=fgets(therm_str,50,datstream))!=NULL)
	{
		num_samples++;
		cput=atoi(therm_str);
		b_queue_addelement(queue, cput);		
	}
	
	/*begin svg writing*/
	
	/*writing svg header*/
	fprintf(svgstream,"<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n");
	
	
	
	/*axis drawing*/
	fprintf(svgstream,"<rect width=\"%d\" height=\"1250\" style=\"fill:rgb(255,255,255);stroke-width:1;stroke:rgb(0,0,0)\"/>\n",(num_samples*X_SCALE)+250);
	
	fprintf(svgstream,"<line x1=\"150\" y1=\"150\" x2=\"150\" y2=\"1150\" style=\"stroke:rgb(9,9,9);stroke-width:2\"/>\n");
	fprintf(svgstream,"<line x1=\"150\" y1=\"1150\" x2=\"%d\" y2=\"1150\" style=\"stroke:rgb(9,9,9);stroke-width:2\"/>\n",(num_samples*X_SCALE)+150);
	
	/*main x-lines drawing*/
	for(i=0; i<=10; i++)
	{
		fprintf(svgstream,"<line x1=\"145\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"stroke:rgb(90,90,90);stroke-width:1\"/>\n",150+i*100,(num_samples*X_SCALE)+150,150+i*100);
		
		/*text rendering*/
		fprintf(svgstream,"<text x=\"130\" y=\"%d\" fill=\"red\">%d</text>\n",150+i*100,100-i*10);
	}
	
	/*x-secondary-lines drawing*/
	for(i=0; i<100; i++)
	{
		fprintf(svgstream,"<line x1=\"150\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"stroke:rgb(200,200,200);stroke-width:1\"/>\n",150+i*10,(num_samples*X_SCALE)+150,150+i*10);
	}
	
	
	/*main y-lines drawing*/
	for(i=0; i<=(int)((double)num_samples/10); i++)
	{
		fprintf(svgstream,"<line x1=\"%d\" y1=\"150\" x2=\"%d\" y2=\"1155\" style=\"stroke:rgb(90,90,90);stroke-width:1\"/>\n",150+i*10*X_SCALE,150+i*10*X_SCALE);
		
		/*text rendering only on even columns*/
		if(i%2==0)
		{
			fprintf(svgstream,"<text x=\"%d\" y=\"1165\" fill=\"red\">%d</text>\n",150+i*10*X_SCALE,i*10);
		}
	}
	
	
	/*secondary y-lines drawing*/
	for(i=0; i<=(int)((double)num_samples/2); i++)
	{
		fprintf(svgstream,"<line x1=\"%d\" y1=\"150\" x2=\"%d\" y2=\"1150\" style=\"stroke:rgb(190,190,190);stroke-width:1\"/>\n",150+i*2*X_SCALE,150+i*2*X_SCALE);
		
	}
	
	
	/*labels*/
	fprintf(svgstream,"<text x=\"50\" y=\"750\" font-size=\"20\" fill=\"black\">T(C)</text>\n");
	fprintf(svgstream,"<text x=\"%d\" y=\"1200\" font-size=\"20\"  fill=\"black\">Samples</text>\n",(int)((double)(num_samples*X_SCALE)/2)+150);
	
	
	
	/*spline drawing*/
	fprintf(svgstream,"<polyline points=\"");
	for(i=0; i<num_samples; i++)
	{
		cput=b_queue_gethead(queue);
		fprintf(svgstream,"%d,%d ",(i*X_SCALE)+150,(1000-cput*10)+150);
		b_queue_delelement(queue);
	}
	fprintf(svgstream,"\" style=\"fill:none;stroke:blue;stroke-width:3\" />\n");
	
	b_queue_free(queue);
	free(queue);
	
	/*writing svg footer*/
	fprintf(svgstream,"</svg>\n");
	
	
	fclose(datstream);
	fclose(svgstream);
	
	printf("File:%s saved!\n\n",svgname);
	
	return 0;
}



int main()
{
	char c='?'; /*used for choice questions*/
	int i=0; /*used for cycles*/
	FILE *stream=NULL; /*used for file existance tests*/
	char *env=NULL; /*used to contain the env value like HOME*/
	int envlen=0; /*env variable length*/
	char *cfgfname=NULL; /*config filename*/
	char cfgstring[1024]; /*config string*/
	char cpu1fname[1024];
	
	
	printf("\nThermcap ver.ALPHA! Read the README to use\n");
	printf("Developed by Giovanni Santostefano http://bitnwoods.wordpress.com\n\n");
	
	
	/*try to get the user home directory*/
	env=getenv("HOME");
	
	if(!env)
	{
		/*not user home*/
		printf("\nError: Please set the HOME environment variable and retry!\n");
		return -5;
	}
	
	/*size a proper config file name string*/
	envlen=strlen(env);
	cfgfname=malloc(envlen+20); /*meglio abbondare*/
	
	/*compose the filename ~/.thermcaprc*/
	strcpy(cfgfname, env);
	strcat(cfgfname,"/.thermcaprc");
	
	/*test if config file exists and if not, create a new one*/
	stream=fopen(cfgfname,"r");
	if(!stream)
	{
		printf("\nNo configuration found!\n");
		printf("New configuration step:\n");
		printf("\nInsert the temperature /proc file name\nusually something like /proc/acpi/thermal_zone/.../temperature)\n");
		printf(">");
		scanf("%s",cfgstring);
		
		/*test for existing path*/
		while(!(stream=fopen(cfgstring,"r")))
		{
			printf("FILE NOT FOUND!\n");
			printf("\nInsert the temperature /proc file name\nusually something like /proc/acpi/thermal_zone/.../temperature)\n");
			printf(">");
			scanf("%s",cfgstring);
		}
		fclose(stream);
		
		/*proc file exists! record the config string*/
		stream=fopen(cfgfname,"w");
		fprintf(stream, "%s",cfgstring); 
	}
	fclose(stream); /*close the stream anywhere*/
	
	
	/*load configuration of the proc temperature file*/
	stream=fopen(cfgfname,"r");
	fgets(cpu1fname,1024,stream);
	fclose(stream);
	
	
	
	/*control for previous data existance*/
	if(stream=fopen("temp.dat","r"))
	{
		printf("A previous data collection was found\n");
		printf("Remove collected data? [y/n]");
		c=getchar();
		fclose(stream);
		
		if(c=='y' || c=='Y')
		{
			printf("You answered %c, data will be permanently destroyed\n\n",c);
			stream=fopen("temp.dat","w");
			fprintf(stream,"");
			fclose(stream);
		}
	}
	
	void (*sighandler)(int); 
	sighandler = signal(SIGINT, signalhandler); 
	
	printf("\n\nUse CTRL+C to terminate program\nCollecting thermal data");
	
	while(1)
	{
		i=thermal_cap("temp.dat",cpu1fname);
		if(i<0)
		{
			printf("Error %d\n\n", i);
			return -1;
		}
		printf(".");
		fflush(NULL);
		sleep(15);
	}
	return 0;
}




void signalhandler(int numsig)
{
	signal(numsig, SIGINT);
	
	
	/*TODO: change this code please!*/
	int i=0;
	int j=0;
	char csvname[100];
	char svgname[100];
	
	time_t t=time(NULL);
	char *f_base_name=ctime(&t);
	
	while(f_base_name[i]!='\0')
	{
		if(f_base_name[i]!=' ' && f_base_name[i]!=':')
		{
			csvname[j]=f_base_name[i];
			svgname[j]=f_base_name[i];
			j++;
		}
		
		i++;
	}
	j--;
	csvname[j]='.';csvname[j+1]='c';csvname[j+2]='s';csvname[j+3]='v';csvname[j+4]='\0';
	svgname[j]='.';svgname[j+1]='s';svgname[j+2]='v';svgname[j+3]='g';svgname[j+4]='\0';
	/*-------*/
	
	
	i=save_csv(csvname);
	
	i=save_svg(svgname);
	
	/*launch the function that creates the SVG graphic*/
	
	printf("\n\nSuccess!! Enjoy your data!\n");
	exit(0);
	
	signal(numsig, signalhandler);  
}

